package com.tree.common.aop;

import com.alibaba.fastjson.JSON;
import com.tree.common.config.i18n.util.WebUtil;
import com.tree.common.util.Log;
import com.tree.common.util.TraceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @ClassName com.demo.common.aop
 * Description: <类功能描述>. <br>
 * <p>
 * <使用说明>
 * </p>
 * @Author tree
 * @Date 2019-05-26 00:59
 * @Version 1.0
 */
@Aspect
@Component
public class AccessLogAop {
    private static final Logger logger = LoggerFactory.getLogger(AccessLogAop.class);

    private static final List<String> IGNORE_REQUEST_PARAM_LIST = new ArrayList<>();
    private static final List<String> METHOD_PREFIX_LIST = new ArrayList<>();
    static {
        IGNORE_REQUEST_PARAM_LIST.add("updateDetailReport");
        METHOD_PREFIX_LIST.add("get");
        METHOD_PREFIX_LIST.add("query");
        METHOD_PREFIX_LIST.add("list");
        METHOD_PREFIX_LIST.add("get");
        METHOD_PREFIX_LIST.add("select");
        METHOD_PREFIX_LIST.add("check");
    }



    @Around("@annotation(org.springframework.web.bind.annotation.PostMapping) " +
            "|| @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public Object audit(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature  = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        String methodName = method.getName();
        Map map = new HashMap();
        map.put("traceId", TraceContextHolder.getCurrentTraceId());
        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            joinPoint.proceed();
            return result;
        }catch (Throwable e){
            throw e;
        }finally {
            boolean needAudit = true;
            for(String methodPrefix  : METHOD_PREFIX_LIST){
                if(methodName.startsWith(methodPrefix)){
                    needAudit =false;
                    break;
                }
            }
            if(needAudit){
                if(!IGNORE_REQUEST_PARAM_LIST.contains(methodName)){
                    Object[] args = joinPoint.getArgs();
                    List<Object> params =  new ArrayList<>();
                    if(args != null && args.length > 0){
                        for(Object arg : args){
                            if(!(arg instanceof HttpServletRequest ) && !(arg instanceof HttpServletResponse)){
                                params.add(arg);
                            }
                        }
                        String paramStr = JSON.toJSONString(params);
                        map.put("params", paramStr);
                    }
                }

                if(method != null ){
                    map.put("functionName", method.getName());
                }
                map.put("remoteId", WebUtil.getRemoteAddr());
                map.put("requestUrl",WebUtil.getPathWithApp());
                map.put("serverIP",WebUtil.getLocalHostIp());
                map.put("executeTime",System.currentTimeMillis()-startTime);
                map.put("createTime",new Date());
//                map.put("userId",UserContextHolder.getUserInfo().getId());
//                map.put("userName",UserContextHolder.getUserInfo().getName());

                logger.debug(Log.op("audit").msg("audit log").kv("log audit info",map).toString());


            }
        }


    }
}
